package com.adams.custom.page.util;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import net.sf.json.JSONArray;

import org.apache.commons.configuration.Configuration;
import org.apache.log4j.Logger;

import com.adams.utils.SystemConfig;

/**
 * 
 * File Name : DataOperateMessageUtil.java
 * 
 * @Description : 数据操作信息工具类
 */
@SuppressWarnings("unchecked")
public class DataOperateMessageUtil
{
	private static Logger logger = Logger
			.getLogger(DataOperateMessageUtil.class.getName());

	public static String MESSAGE_PARAM = "dataOperateMessage";

	public static String DELETE_ACTION_TYPE = "delete";

	public static String UPDATE_ACTION_TYPE = "update";

	public static String CREATE_ACTION_TYPE = "create";

	public static String ACTION_TYPE = "actionType";

	public static String TABLE_NAME = "tablename";

	private static ThreadLocal<List<Map<String, String>>> dataOperateMessagesThreadLocal = new ThreadLocal<List<Map<String, String>>>()
	{
		protected synchronized List<Map<String, String>> initialValue()
		{
			return new ArrayList<Map<String, String>>();
		}
	};

	/**
	 * Description : 得到数据操作信息列表
	 * 
	 * @return
	 * 
	 */
	private static List<Map<String, String>> getDataOperateMessages()
	{
		List<Map<String, String>> cacheMessages = dataOperateMessagesThreadLocal
				.get();
		return cacheMessages;
	}

	/**
	 * Description : 增加数据操作信息
	 * 
	 * @param cacheMessage
	 * 
	 */
	public static void addDataOperateMessage(Map<String, String> cacheMessage)
	{
		getDataOperateMessages().add(cacheMessage);
	}

	/**
	 * Description : 增加数据操作信息
	 * 
	 * @param cacheMessages
	 * 
	 */
	public static void addDataOperateMessages(
			List<Map<String, String>> cacheMessages)
	{
		List<Map<String, String>> cache = dataOperateMessagesThreadLocal.get();
		cache.addAll(cacheMessages);
	}

	/**
	 * Description : 清空数据操作信息
	 * 
	 * 
	 */
	public static void clearDataOperateMessages()
	{
		List<Map<String, String>> list = getDataOperateMessages();
		if (null != list)
		{
			list.clear();
		}
	}

	/**
	 * Description : 发送数据操作信息
	 * 
	 * 
	 */
	public static void sendDataOperateMessages()
	{
		List<Map<String, String>> cache = dataOperateMessagesThreadLocal.get();
		Set<String> tablecodes = new HashSet<String>();
		for (Map<String, String> message : cache)
		{
			if (!ViewUtil.isNuLLValueInMap(message, TABLE_NAME))
			{
				String tablecode = message.get(TABLE_NAME);
				tablecodes.add(tablecode);
			}
		}
		if (tablecodes.size() > 0)
		{
			String messages = JSONArray.fromObject(cache).toString();
			Set<String> addressSet = getSendAddresss(tablecodes);
			if (addressSet.size() > 0)
			{
				sendMessage(addressSet, messages);
			}
		}
		clearDataOperateMessages();
	}

	private static ThreadLocal<Stack<String>> methodStackThreadLocal = new ThreadLocal<Stack<String>>()
	{
		protected synchronized Stack<String> initialValue()
		{
			return new Stack<String>();
		}
	};

	/**
	 * Description : 把线程运行方法放入栈
	 * 
	 * @param methodName
	 * 
	 */
	public static void pushMethodName(String methodName)
	{
		Stack<String> result = methodStackThreadLocal.get();
		result.push(methodName);
	}

	/**
	 * Description : 当前运行方法出栈并返回栈内是否为空 此方法主要用于判断此方法是否为线程首运行方法
	 * 
	 * @return
	 * 
	 */
	public static boolean isEmptyMethodStack()
	{
		Stack<String> stack = methodStackThreadLocal.get();
		if (!stack.isEmpty())
		{
			stack.pop();
		}
		return stack.isEmpty();
	}

	/**
	 * Description : 需要发送的表及地址映射 Author : 904370
	 */
	private static Map<String, Set<String>> sendTablecodeAddressMap = new HashMap<String, Set<String>>();

	// 初始化需要通知的地址及表
	static
	{

		Configuration configuration = SystemConfig.getInstance()
				.getConfiguration();
		Map<String, String> keyAddressMap = new HashMap<String, String>();
		Map<String, Set<String>> keyTablecodesMap = new HashMap<String, Set<String>>();
		for (Iterator keyIt = configuration.getKeys(); keyIt.hasNext();)
		{
			String key = (String) keyIt.next();
			if (ViewUtil.isNuLLStr(key))
			{
				continue;
			}
			String businessName = null;
			String urlfalg = ".data.operate.send.url";
			String tablefalg = ".data.operate.send.tablecodes";
			if (key.endsWith(urlfalg))
			{
				businessName = key
						.substring(0, key.length() - urlfalg.length());
				String value = configuration.getString(key);
				if (ViewUtil.isNuLLStr(value))
				{
					continue;
				}
				keyAddressMap.put(businessName, value);
				continue;
			}
			if (key.endsWith(tablefalg))
			{
				businessName = key.substring(0, key.length()
						- tablefalg.length());
				String[] values = configuration.getStringArray(key);
				Set<String> tablecodeSet = new HashSet<String>();
				int valueslen = values.length;
				for (int i = 0; i < valueslen; i++)
				{
					String value = values[i];
					if (!ViewUtil.isNuLLStr(value))
					{
						tablecodeSet.add(value);
					}
				}
				keyTablecodesMap.put(businessName, tablecodeSet);
				continue;
			}
		}
		for (Iterator<String> keyIt = keyAddressMap.keySet().iterator(); keyIt
				.hasNext();)
		{
			String key = (String) keyIt.next();
			String address = keyAddressMap.get(key);
			Set<String> tablecodeSet = keyTablecodesMap.get(key);
			if (tablecodeSet.size() == 0)
			{
				continue;
			}
			putSendAddress(address, tablecodeSet);
		}
	}

	/**
	 * Description : 放入发送地址及相关表
	 * 
	 * @param address
	 * @param tablecodes
	 * 
	 */
	public static void putSendAddress(String address, Set<String> tablecodes)
	{
		for (String tablecode : tablecodes)
		{
			Set<String> addressSet = null;
			if (sendTablecodeAddressMap.containsKey(tablecode))
			{
				addressSet = sendTablecodeAddressMap.get(tablecode);
			} else
			{
				addressSet = new HashSet<String>();
			}
			addressSet.add(address);
			sendTablecodeAddressMap.put(tablecode, addressSet);
		}
	}

	/**
	 * Description : 根据表得到需要发送的地址
	 * 
	 * @param tablecodes
	 * @return
	 * 
	 */
	private static Set<String> getSendAddresss(Set<String> tablecodes)
	{
		Set<String> allAddress = new HashSet<String>();
		for (String tablecode : tablecodes)
		{
			if (sendTablecodeAddressMap.containsKey(tablecode))
			{
				Set<String> addressSet = sendTablecodeAddressMap.get(tablecode);
				if (null != addressSet && addressSet.size() > 0)
				{
					allAddress.addAll(addressSet);
				}
			}
		}
		return allAddress;
	}

	/**
	 * Description : 向地址列表发送数据操作信息
	 * 
	 * @param addressSet
	 * @param message
	 * 
	 */
	private static void sendMessage(Set<String> addressSet, String message)
	{
		for (String address : addressSet)
		{
			if (!ViewUtil.isNuLLStr(address))
			{
				createSendMessageTask(address, message);
			}
		}
	}

	/**
	 * Description : 创建发送数据操作信息任务
	 * 
	 * @param address
	 * @param message
	 * 
	 */
	private static void createSendMessageTask(String address, String message)
	{
		DataOperateMessageUtil.SendMessageTask sendMessageTask = new DataOperateMessageUtil.SendMessageTask(
				address, message);
		minPriorityExecutor.execute(sendMessageTask);
	}

	/**
	 * Description : 低优先级线程工厂 Author : 904370
	 */
	private static ExecutorService minPriorityExecutor = Executors
			.newSingleThreadExecutor(new ThreadFactory()
			{
				@Override
				public Thread newThread(Runnable r)
				{
					Thread t = new Thread(r);
					t.setPriority(Thread.MIN_PRIORITY);
					return t;
				}
			});

	/**
	 * 
	 * File Name : DataOperateMessageUtil.java
	 * 
	 * @Description : 发送数据操作信息任务
	 * @author 904370 张汉辉
	 */
	public static class SendMessageTask implements Runnable
	{
		private String address;

		private String message;

		public SendMessageTask(String address, String message)
		{
			this.address = address;
			this.message = message;
		}

		@Override
		public void run()
		{
			try
			{
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					for(int i=0;i<0x40000;i++){
						continue;
					}
				}
				URL url = new URL(address);
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.setRequestMethod("POST");
				conn.setRequestProperty("Content-Type",
						"application/x-www-form-urlencoded");
				conn.setRequestProperty("Connection", "Keep-Alive");
				conn.setUseCaches(false);
				conn.setDoOutput(true);
				OutputStreamWriter out = new OutputStreamWriter(conn
						.getOutputStream(), "utf-8");
				out.write(MESSAGE_PARAM);
				out.write("=");
				out.write(message);
				out.flush();
				out.close();
				if (conn.getResponseCode() != HttpURLConnection.HTTP_OK)
				{
					logger.error("发送缓存更新信息失败!");
				}
			} catch (MalformedURLException e)
			{
				logger.error("发送缓存更新信息失败!", e);
			} catch (IOException e)
			{
				logger.error("发送缓存更新信息失败!", e);
			}
			logger.info("发送缓存更新信息 url:"+address);
		}
	}
}
